import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 生成模拟数据
np.random.seed(42)  # 固定随机种子以确保结果可重复
n = 1000  # 数据点数量
log2_fold_change = np.random.normal(0, 1, n)  # 对数倍数变化 (log2 fold change)
p_values = np.random.uniform(0, 1, n)  # 随机生成P值
neg_log10_p_values = -np.log10(p_values)  # 负对数转换后的P值

# 创建DataFrame存储数据
data = pd.DataFrame({
    'log2_fold_change': log2_fold_change,
    'neg_log10_p_value': neg_log10_p_values
})

# 定义显著性阈值
fold_change_threshold = 1  # log2倍数变化阈值 (|log2FC| > 1)
p_value_threshold = -np.log10(0.05)  # P值阈值 (-log10(P) > -log10(0.05))

# 标记显著上调、显著下调和非显著的点
data['significance'] = 'Not Significant'
data.loc[(data['log2_fold_change'] > fold_change_threshold) &
         (data['neg_log10_p_value'] > p_value_threshold), 'significance'] = 'Upregulated'
data.loc[(data['log2_fold_change'] < -fold_change_threshold) &
         (data['neg_log10_p_value'] > p_value_threshold), 'significance'] = 'Downregulated'

# 绘制火山图
plt.figure(figsize=(10, 6))
colors = {'Upregulated': 'red', 'Downregulated': 'blue', 'Not Significant': 'gray'}
for group, color in colors.items():
    subset = data[data['significance'] == group]
    plt.scatter(subset['log2_fold_change'], subset['neg_log10_p_value'],
                c=color, label=group, alpha=0.7, s=20)

# 添加阈值线
plt.axhline(y=p_value_threshold, color='black', linestyle='--', linewidth=1)
plt.axvline(x=fold_change_threshold, color='black', linestyle='--', linewidth=1)
plt.axvline(x=-fold_change_threshold, color='black', linestyle='--', linewidth=1)

# 设置图表标题和标签
plt.title('Volcano Plot of Differential Expression Analysis', fontsize=16)
plt.xlabel('Log2 Fold Change', fontsize=14)
plt.ylabel('-Log10 P-value', fontsize=14)
plt.legend(title='Significance', loc='upper left', fontsize=10)
plt.grid(alpha=0.3)

# 显示图形
plt.tight_layout()
plt.show()